package com.gpl.service;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 1）I/O：各种各样的流（文件、数组、缓冲、管道）的处理（输入输出）；NIO
 * 2）Channel：通道，代表一个连接，每个Client请对会对应到具体的一个Channel；
 * 3）ChannelPipeline：责任链，每个Channel都有且仅有一个ChannelPipeline与之对应，里面是各种各样的Handler；
 * 4）handler：用于处理出入站消息及相应的事件，实现我们自己要的业务逻辑；
 * 5）EventLoopGroup：I/O线程池，负责处理Channel对应的I/O事件；
 * 6）ServerBootstrap：服务器端启动辅助对象；
 * 7）Bootstrap：客户端启动辅助对象
 * 8）ChannelInitializer：Channel初始化器；
 * 9）ChannelFuture：代表I/O操作的执行结果，通过事件机制，获取执行结果，通过添加监听器，执行我们想要的操作；
 * 10）ByteBuf：字节序列，通过ByteBuf操作基础的字节数组和缓冲区。
 * 11) ChannelHandlerContext  建立通道后的上下文
 *
 *
 *  ServerBootstrap：服务器端启动辅助对象；
 *      ServerBootstrap  设置IO模型NioEventLoopGroup
 *      ServerBootstrap  设置线程模型NioEventLoopGroup
 *
 * Channel：通道，代表一个连接，每个Client请对会对应到具体的一个Channel；
 *   ChannelPipeline：责任链，每个Channel都有且仅有一个ChannelPipeline与之对应，里面是各种各样的Handler；
 */
@Service
public class IOVServer extends Thread{

    @Autowired
    IOVServerHandler iovServerHandler;


    @Override
    public void run(){
        ServerBootstrap bootstrap = new ServerBootstrap();//1、服务器端 引导程序   开餐馆

        EventLoopGroup bossGroup = new NioEventLoopGroup();// Group 领班 EventLoop  迎宾员  处理连接事件
        EventLoopGroup workerGroup = new NioEventLoopGroup();// Group 领班 EventLoop  服务员  处理读写IO 事件

        try {
            int port = 8564;
            bootstrap
                    .channel(NioServerSocketChannel.class)//IO模型=NIO  连接事件  读事件
                    //.group(bossGroup)//单线程 线程模型
                    .group(bossGroup, workerGroup)//多线程 线程模型
                    .localAddress(port)//绑定端口 餐馆位置
                    .childHandler(new ChannelInitializer<SocketChannel>() {//告诉服务 干的具体的活
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //ChannelPipeline
                            //分包器
                            socketChannel.pipeline().addLast(new DelimiterBasedFrameDecoder(4096, Unpooled.copiedBuffer("#$&*".getBytes())));

                            // 解码器
                            socketChannel.pipeline().addLast("encoder", new StringEncoder());
                            socketChannel.pipeline().addLast("decoder", new StringDecoder());
                            socketChannel.pipeline().addLast(new IOVServerHandler());
                        }
                    }); // 处理具体的业务，链式处理

            //开始营业，接收连接,sync 同步调用，直到调用成功才进行下一步
            ChannelFuture future = bootstrap.bind().sync();
            if (future.isSuccess()) {
                System.out.println(IOVServer.class.getName() + " 启动并监听端口：" + future.channel().localAddress());
            }
            //等待直到通道关闭   直到客户断开，我们将该通道关闭
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
